﻿Imports System.Text.RegularExpressions
Imports System.Collections
Imports System.Collections.Generic

Public Class GerenteDeSenha
    Inherits PadroesForcaSenha

#Region "Construtores"

    Public Sub New()
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

    Public Sub New(ByVal _senhaDeveConterNumeros As Boolean, ByVal _senhaDeveConterLetras As Boolean)
        MyBase.ExigeLetras = _senhaDeveConterLetras
        MyBase.ExigeNumeros = _senhaDeveConterNumeros
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

    Public Sub New(ByVal _senhaDeveConterNumeros As Boolean, ByVal _senhaDeveConterLetras As Boolean, ByVal _notaMinimaParaSenhaSerForte As Integer)
        MyBase.ExigeLetras = _senhaDeveConterLetras
        MyBase.ExigeNumeros = _senhaDeveConterNumeros
        If _notaMinimaParaSenhaSerForte = 0 OrElse _notaMinimaParaSenhaSerForte < 50 Then
            Throw New SenhaFracaException("Nota mimina da senha deve ser igual ou superior a 50")
        End If
        MyBase.NotaMinimaParaContinuar = _notaMinimaParaSenhaSerForte
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

    Public Sub New(ByVal _senhaDeveConterNumeros As Boolean, ByVal _senhaDeveConterLetras As Boolean, ByVal _notaMinimaParaSenhaSerForte As Integer, _
                   ByVal _numeroMinimoDeCaracteresNaSenha As Integer)
        MyBase.ExigeLetras = _senhaDeveConterLetras
        MyBase.ExigeNumeros = _senhaDeveConterNumeros

        If _notaMinimaParaSenhaSerForte = 0 AndAlso _notaMinimaParaSenhaSerForte < 50 Then
            Throw New SenhaFracaException("Nota mimina da senha deve ser igual ou superior a 50")
        End If
        MyBase.NotaMinimaParaContinuar = _notaMinimaParaSenhaSerForte
        MyBase.MinimoCaracteresSenha = _numeroMinimoDeCaracteresNaSenha
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

    Public Sub New(ByVal _senhaDeveConterNumeros As Boolean, ByVal _senhaDeveConterLetras As Boolean, ByVal _notaMinimaParaSenhaSerForte As Integer, _
               ByVal _numeroMinimoDeCaracteresNaSenha As Integer, ByVal _senhaDeveConterLetrasMaiusculas As Boolean)
        MyBase.ExigeLetras = _senhaDeveConterLetras
        MyBase.ExigeNumeros = _senhaDeveConterNumeros

        If _notaMinimaParaSenhaSerForte = 0 AndAlso _notaMinimaParaSenhaSerForte < 50 Then
            Throw New SenhaFracaException("Nota mimina da senha deve ser igual ou superior a 50")
        End If
        MyBase.NotaMinimaParaContinuar = _notaMinimaParaSenhaSerForte
        MyBase.MinimoCaracteresSenha = _numeroMinimoDeCaracteresNaSenha
        MyBase.ExigeMaiusculas = _senhaDeveConterLetrasMaiusculas
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

    Public Sub New(ByVal _senhaDeveConterNumeros As Boolean, ByVal _senhaDeveConterLetras As Boolean, ByVal _notaMinimaParaSenhaSerForte As Integer, _
           ByVal _numeroMinimoDeCaracteresNaSenha As Integer, ByVal _senhaDeveConterLetrasMaiusculas As Boolean, _
           ByVal _senhaDeveConterCaracteresEspeciais As Boolean)
        MyBase.ExigeLetras = _senhaDeveConterLetras
        MyBase.ExigeNumeros = _senhaDeveConterNumeros

        If _notaMinimaParaSenhaSerForte = 0 AndAlso _notaMinimaParaSenhaSerForte < 50 Then
            Throw New SenhaFracaException("Nota mimina da senha deve ser igual ou superior a 50")
        End If
        MyBase.NotaMinimaParaContinuar = _notaMinimaParaSenhaSerForte
        MyBase.MinimoCaracteresSenha = _numeroMinimoDeCaracteresNaSenha
        MyBase.ExigeMaiusculas = _senhaDeveConterLetrasMaiusculas
        MyBase.ExigeSimbolos = _senhaDeveConterCaracteresEspeciais
        Me.ArrayCaracteresSenha = New List(Of String)
    End Sub

#End Region

    Private _senhasGeradas As IList(Of String)
    Protected Property SenhasGeradas() As IList(Of String)
        Get
            Return _senhasGeradas
        End Get
        Set(ByVal value As IList(Of String))
            _senhasGeradas = value
        End Set
    End Property

    Protected ReadOnly Property LetrasMaiusculas() As String
        Get
            Return "ABCDEFGHIJLMNOPQRSTUVXZWYK"
        End Get
    End Property

    Protected ReadOnly Property LetrasMinusculas() As String
        Get
            Return "abcdefghijklmnopqrstuvwxyz"
        End Get
    End Property

    Protected ReadOnly Property Numeros() As String
        Get
            Return "1234567890"
        End Get
    End Property

    Protected ReadOnly Property CaracteresEspeciais() As String
        Get
            Return "!@#$%&*()_-+?]}[{~^\/"
        End Get
    End Property


    Private _arrayCaracteresSenha As IList(Of String)
    Protected Property ArrayCaracteresSenha() As IList(Of String)
        Get
            Return _arrayCaracteresSenha
        End Get
        Set(ByVal value As IList(Of String))
            _arrayCaracteresSenha = value
        End Set
    End Property

    Protected Shared ValidaPasswordDigits As Regex = New Regex("\d", RegexOptions.Compiled)
    Protected Shared ValidaPasswordNonWord As Regex = New Regex("\W", RegexOptions.Compiled)
    Protected Shared ValidaPasswordUppercase As Regex = New Regex("[A-Z]", RegexOptions.Compiled)
    Protected Shared ValidaPasswordLowercase As Regex = New Regex("[a-z]", RegexOptions.Compiled)

    Public Function RetornarNotaSenha(ByVal _senha As String) As Integer

        Dim _obrigaNumeros As Boolean
        Dim _obrigaLetras As Boolean
        Dim _obrigaMaiusculas As Boolean
        Dim _obrigaCaracteresEspeciais As Boolean
        Dim _notaFinal As Integer

        Dim _notaNumeros As Integer
        Dim _notaLetras As Integer
        Dim _notaCaracteresEspeciais As Integer
        Dim _notaTamanho As Integer
        Dim _notaCaracteresRepetidos As Integer

        Me.VerificaPadroesIniciais()

        _obrigaCaracteresEspeciais = MyBase.ExigeSimbolos
        _obrigaLetras = MyBase.ExigeLetras
        _obrigaNumeros = MyBase.ExigeNumeros
        _obrigaMaiusculas = MyBase.ExigeMaiusculas

        _notaTamanho = Me.NotaTamanhoSenha(_senha)

        If _notaTamanho <= 0 Then
            Return 0
        End If

        If _obrigaNumeros Then
            _notaNumeros = Me.NotaExisteNumeros(_senha)
        End If

        If _obrigaLetras OrElse _obrigaMaiusculas Then
            _notaLetras = Me.NotaExisteLetras(_senha, _obrigaMaiusculas)
        End If

        If _obrigaCaracteresEspeciais Then
            _notaCaracteresEspeciais = Me.NotaExisteCaracteres(_senha)
        End If

        _notaCaracteresRepetidos = Me.VerificaCaracteresRepetidos(_senha)

        _notaFinal = _notaCaracteresEspeciais + _notaLetras + _notaNumeros + _notaTamanho + _notaCaracteresRepetidos

        'Console.WriteLine("Caracter especial: {0}, Letras (upper/lower): {1}, Números: {2}, Tamanho: {3} + Repetidos: {4} = Final {5}", _notaCaracteresEspeciais, _notaLetras, _notaNumeros, _notaTamanho, _notaCaracteresRepetidos, _notaFinal)

        Return _notaFinal

    End Function

    Public Function SenhaEhForte(ByVal _senha As String) As Boolean

        Dim _nota As Integer

        _nota = Me.RetornarNotaSenha(_senha)

        If _nota = 0 Then
            Return False
        End If

        If _nota < MyBase.NotaMinimaParaContinuar Then
            Return False
        End If

        Return True

    End Function

    Public Function GerarSenhaForte() As String

        Dim _obrigaNumeros As Boolean
        Dim _obrigaLetras As Boolean
        Dim _obrigaMaiusculas As Boolean
        Dim _obrigaCaracteresEspeciais As Boolean
        Dim _senha As String
        Dim _senhaForteCorreta As Boolean
        Dim _senhasGeradasSessao As IList(Of String)

        If Me.SenhasGeradas Is Nothing Then
            _senhasGeradasSessao = New List(Of String)
        Else
            _senhasGeradasSessao = Me.SenhasGeradas
        End If

        Me.VerificaPadroesIniciais()

        _senha = String.Empty
        _obrigaCaracteresEspeciais = MyBase.ExigeSimbolos
        _obrigaLetras = MyBase.ExigeLetras
        _obrigaNumeros = MyBase.ExigeNumeros
        _obrigaMaiusculas = MyBase.ExigeMaiusculas

        While _senhaForteCorreta = False
            _senha = Me.GerarSenha(MyBase.MinimoCaracteresSenha, _obrigaLetras, _obrigaMaiusculas, _obrigaNumeros, _obrigaCaracteresEspeciais)
            _senhaForteCorreta = Me.SenhaEhForte(_senha)
        End While

        If Me.SenhaJaFoiGeradaNaSessao(_senha) Then
            _senhasGeradasSessao.Add(_senha)
            Me.SenhasGeradas = _senhasGeradasSessao
            Return _senha
        Else
            Return GerarSenhaForte()
        End If

    End Function

#Region "Validações"

    Protected Function NotaTamanhoSenha(ByVal _senha As String) As Integer

        Dim _tamanhoMinimo As Integer = MyBase.MinimoCaracteresSenha
        Dim _tamanhoSenhaEnviada As Integer
        Dim _notaSenhaTamanho As Integer = MyBase.NotaTamanhoMinimo

        _tamanhoSenhaEnviada = _senha.Length

        If _tamanhoSenhaEnviada >= _tamanhoMinimo Then
            Return _notaSenhaTamanho
        Else
            Return -1
        End If

    End Function

    Protected Function NotaExisteNumeros(ByVal _senha As String) As Integer

        Dim _pontuacao As Integer = MyBase.NotaExisteNumero

        If Not ValidaPasswordDigits.IsMatch(_senha) Then
            Return -_pontuacao
        End If

        Return _pontuacao

    End Function

    Protected Function NotaExisteLetras(ByVal _senha As String, ByVal _exigeMaiusculas As Boolean) As Integer
        Dim _notaLetras As Integer = MyBase.NotaExisteMinuscula
        Dim _notaMaiuscula As Integer = MyBase.NotaExisteMaiuscula
        Dim _notaFinal As Integer


        If Not ValidaPasswordLowercase.IsMatch(_senha) Then
            _notaLetras = -_notaLetras
        End If

        If _exigeMaiusculas Then
            If Not ValidaPasswordUppercase.IsMatch(_senha) Then
                _notaMaiuscula = -_notaMaiuscula
            End If

            _notaFinal = _notaMaiuscula + _notaLetras
        Else

            _notaFinal = _notaLetras

        End If

        Return _notaFinal

    End Function

    Protected Function NotaExisteCaracteres(ByVal _senha As String) As Integer

        Dim _pontuacao As Integer = MyBase.NotaExisteCaracteresNaSenha

        If Not ValidaPasswordNonWord.IsMatch(_senha) Then
            Return -_pontuacao
        End If

        Return _pontuacao

    End Function

    Protected Function VerificaCaracteresRepetidos(ByVal _senha As String) As Integer

        Dim _repetidos As Integer = 0
        Dim _arrCaracteres() As Char
        _arrCaracteres = _senha.ToArray()
        '''' analisa se os caracteres são 
        '''' repitidos e retira 1 ponto a cada caracter repetido em sequência
        For i As Integer = 1 To _arrCaracteres.Length

            If (i + 1) < _arrCaracteres.Length Then

                If _arrCaracteres(i).GetHashCode() = _arrCaracteres(i + 1).GetHashCode() Then
                    _repetidos -= 1
                End If

            End If
        Next

        Return _repetidos

    End Function

#End Region

#Region "Gerador Senha"

    Protected Sub VerificaPadroesIniciais()

        Dim _pesoPadrao As Integer
        Dim _totalRegrasSelecionadas As Integer

        _pesoPadrao = Convert.ToInt32(100 / 5)

        If MyBase.ExigeLetras = False AndAlso MyBase.ExigeMaiusculas = False AndAlso MyBase.ExigeNumeros = False AndAlso MyBase.ExigeSimbolos = False Then
            MyBase.ExigeNumeros = True
            MyBase.ExigeLetras = True
        End If

        If MyBase.NotaMinimaParaContinuar = 0 Then
            Throw New SenhaFracaException("Nota mímina para que a senha seja validada deve ser informada.")
        End If

        If MyBase.NotaExisteNumero = 0 AndAlso MyBase.NotaExisteMinuscula = 0 AndAlso MyBase.NotaExisteMaiuscula = 0 AndAlso MyBase.NotaExisteCaracteresNaSenha = 0 Then
            MyBase.NotaExisteNumero = _pesoPadrao
            MyBase.NotaExisteMinuscula = _pesoPadrao
            MyBase.NotaExisteMaiuscula = _pesoPadrao
            MyBase.NotaExisteCaracteresNaSenha = _pesoPadrao
            MyBase.NotaTamanhoMinimo = _pesoPadrao
        End If

        If MyBase.MinimoCaracteresSenha = 0 OrElse MyBase.MinimoCaracteresSenha < 8 Then
            MyBase.MinimoCaracteresSenha = 8
        End If

        _totalRegrasSelecionadas = MyBase.NotaTamanhoMinimo

        If MyBase.ExigeLetras Then _totalRegrasSelecionadas += MyBase.NotaExisteMinuscula
        If MyBase.ExigeMaiusculas Then _totalRegrasSelecionadas += MyBase.NotaExisteMaiuscula
        If MyBase.ExigeNumeros Then _totalRegrasSelecionadas += MyBase.NotaExisteNumero
        If MyBase.ExigeSimbolos Then _totalRegrasSelecionadas += MyBase.NotaExisteCaracteresNaSenha

        If _totalRegrasSelecionadas < MyBase.NotaMinimaParaContinuar Then
            Throw New SenhaFracaException("Configurações aplicadas não é válida, o total dos padroes informado é inferior a Nota minima para que a senha seja indicada como forte.")
        End If

    End Sub

    Protected Function GerarSenha(ByVal _tamanhoSenha As Integer, ByVal _exigeLetras As Boolean, ByVal _exigeMaiusculas As Boolean, ByVal _exigeNumeros As Boolean, ByVal _exigeSimbolos As Boolean) As String

        Dim _senhaGerada As String
        Dim _continua As Boolean = False
        _senhaGerada = String.Empty

        _senhaGerada = CriaSenhaFinal()

        Return _senhaGerada
    End Function

    Protected Function CriaSenhaFinal() As String

        Dim _senhaGerada As String
        Dim _startIndex As Integer
        Dim _endIndex As Integer
        Dim _finaliza As Boolean
        Dim _caracterSelecionado As String
        Dim _posicaoArraySelecionado As Integer
        Dim _random As Random

        If MyBase.ExigeLetras Then Me.AdicionarLetrasMinusculasNaLista()
        If MyBase.ExigeMaiusculas Then Me.AdicionarLetrasMaiusculasNaLista()
        If MyBase.ExigeNumeros Then Me.AdicionarNumeroNaLista()
        If MyBase.ExigeSimbolos Then Me.AdicionaSimboloNaListaLista()

        _startIndex = 0
        _endIndex = (Me.ArrayCaracteresSenha.Count - 1)
        _senhaGerada = String.Empty
        _random = New Random()
        While _finaliza = False

            _posicaoArraySelecionado = _random.Next(_startIndex, _endIndex)
            _caracterSelecionado = Me.ArrayCaracteresSenha(_posicaoArraySelecionado)
            If Not _senhaGerada.Contains(_caracterSelecionado) Then
                _senhaGerada += _caracterSelecionado
            End If

            If _senhaGerada.Length >= MyBase.MinimoCaracteresSenha Then
                _finaliza = True
            End If

        End While

        _senhaGerada = Me.ValidaSenhaECorrigeGerada(_senhaGerada)

        Return _senhaGerada

    End Function

    Protected Function ValidaSenhaECorrigeGerada(ByVal _senhaGerada As String) As String

        Dim _arrLetrasMinusculas() As Char
        Dim _arrLetrasMaiusculas() As Char
        Dim _arrNumeros() As Char
        Dim _arrSimbolos() As Char
        Dim _starIndex As Integer
        Dim _endIndex As Integer
        Dim _random As Random
        Dim _posicoesSelecionadasSenha As IList(Of Integer)

        _random = New Random()
        _posicoesSelecionadasSenha = New List(Of Integer)
        _arrLetrasMinusculas = Me.LetrasMinusculas.ToCharArray()
        _arrLetrasMaiusculas = Me.LetrasMaiusculas.ToCharArray()
        _arrNumeros = Me.Numeros.ToCharArray()
        _arrSimbolos = Me.CaracteresEspeciais.ToCharArray()


        If Me.ExigeNumeros Then
            Me.AdicionaNumeroNaSenha(_senhaGerada, _arrNumeros, _random, _starIndex, _endIndex, _posicoesSelecionadasSenha)
        End If

        If Me.ExigeSimbolos Then
            Me.AdicionaSimbolosNaSenha(_senhaGerada, _arrSimbolos, _random, _starIndex, _endIndex, _posicoesSelecionadasSenha)
        End If

        If Me.ExigeMaiusculas Then
            Me.AdicionaLetraMaiusculaNaSenha(_senhaGerada, _arrLetrasMaiusculas, _random, _starIndex, _endIndex, _posicoesSelecionadasSenha)
        End If

        If Me.ExigeLetras Then
            Me.AdicionaLetraMinusculaNaSenha(_senhaGerada, _arrLetrasMinusculas, _random, _starIndex, _endIndex, _posicoesSelecionadasSenha)
        End If

        Return _senhaGerada

    End Function

    Protected Sub AdicionaNumeroNaSenha(ByRef _senhaGerada As String, ByVal _arrNumeros() As Char, ByVal _random As Random, ByVal _starIndex As Integer, ByVal _endIndex As Integer, ByRef _posicoesSelecionadas As IList(Of Integer))

        Dim _posicaoSelecionada As Integer
        Dim _numeroStringSelecionado As String
        Dim _contemNumeros As Boolean
        Dim _posicaoJaSelecionada As Boolean

        For Each item As Char In _arrNumeros
            If _senhaGerada.Contains(item) Then
                _contemNumeros = True
                Exit For
            End If
        Next

        If Not _contemNumeros Then

            _starIndex = 0
            _endIndex = (_arrNumeros.Length - 1)
            _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
            _numeroStringSelecionado = _arrNumeros(_posicaoSelecionada)

            _endIndex = (_senhaGerada.Length - 1)
            _posicaoJaSelecionada = True
            While _posicaoJaSelecionada
                _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
                Dim _result = (From a As Integer In _posicoesSelecionadas Where a = _posicaoSelecionada Select a)
                If _result Is Nothing OrElse _result.Count() = 0 Then
                    _posicaoJaSelecionada = False
                End If
            End While
            _senhaGerada = _senhaGerada.Insert(_posicaoSelecionada, _numeroStringSelecionado)
            If _posicaoSelecionada = 0 Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada + 1, 1)
            ElseIf _posicaoSelecionada = _endIndex Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 2, 1)
            Else
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 1, 1)
            End If

        End If

    End Sub

    Protected Sub AdicionaSimbolosNaSenha(ByRef _senhaGerada As String, ByVal _arrSimbolos() As Char, ByVal _random As Random, ByVal _starIndex As Integer, ByVal _endIndex As Integer, ByRef _posicoesSelecionadas As IList(Of Integer))

        Dim _posicaoSelecionada As Integer
        Dim _numeroStringSelecionado As String
        Dim _contemNumeros As Boolean
        Dim _posicaoJaSelecionada As Boolean

        For Each item As Char In _arrSimbolos
            If _senhaGerada.Contains(item) Then
                _contemNumeros = True
                Exit For
            End If
        Next

        If Not _contemNumeros Then

            _starIndex = 0
            _endIndex = (_arrSimbolos.Length - 1)
            _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
            _numeroStringSelecionado = _arrSimbolos(_posicaoSelecionada)

            _endIndex = (_senhaGerada.Length - 1)
            _posicaoJaSelecionada = True
            While _posicaoJaSelecionada
                _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
                Dim _result = (From a As Integer In _posicoesSelecionadas Where a = _posicaoSelecionada Select a)
                If _result Is Nothing OrElse _result.Count() = 0 Then
                    _posicaoJaSelecionada = False
                End If
            End While
            _senhaGerada = _senhaGerada.Insert(_posicaoSelecionada, _numeroStringSelecionado)
            If _posicaoSelecionada = 0 Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada + 1, 1)
            ElseIf _posicaoSelecionada = _endIndex Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 2, 1)
            Else
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 1, 1)
            End If

        End If

    End Sub

    Protected Sub AdicionaLetraMaiusculaNaSenha(ByRef _senhaGerada As String, ByVal _arrLetrasMaiusculas() As Char, ByVal _random As Random, ByVal _starIndex As Integer, ByVal _endIndex As Integer, ByRef _posicoesSelecionadas As IList(Of Integer))

        Dim _posicaoSelecionada As Integer
        Dim _numeroStringSelecionado As String
        Dim _contemNumeros As Boolean
        Dim _posicaoJaSelecionada As Boolean

        For Each item As Char In _arrLetrasMaiusculas
            If _senhaGerada.Contains(item) Then
                _contemNumeros = True
                Exit For
            End If
        Next

        If Not _contemNumeros Then

            _starIndex = 0
            _endIndex = (_arrLetrasMaiusculas.Length - 1)
            _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
            _numeroStringSelecionado = _arrLetrasMaiusculas(_posicaoSelecionada)

            _endIndex = (_senhaGerada.Length - 1)
            _posicaoJaSelecionada = True
            While _posicaoJaSelecionada
                _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
                Dim _result = (From a As Integer In _posicoesSelecionadas Where a = _posicaoSelecionada Select a)
                If _result Is Nothing OrElse _result.Count() = 0 Then
                    _posicaoJaSelecionada = False
                End If
            End While
            _senhaGerada = _senhaGerada.Insert(_posicaoSelecionada, _numeroStringSelecionado)
            If _posicaoSelecionada = 0 Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada + 1, 1)
            ElseIf _posicaoSelecionada = _endIndex Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 2, 1)
            Else
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 1, 1)
            End If

        End If

    End Sub

    Protected Sub AdicionaLetraMinusculaNaSenha(ByRef _senhaGerada As String, ByVal _arrLetrasMinusculas() As Char, ByVal _random As Random, ByVal _starIndex As Integer, ByVal _endIndex As Integer, ByRef _posicoesSelecionadas As IList(Of Integer))

        Dim _posicaoSelecionada As Integer
        Dim _numeroStringSelecionado As String
        Dim _contemNumeros As Boolean
        Dim _posicaoJaSelecionada As Boolean

        For Each item As Char In _arrLetrasMinusculas
            If _senhaGerada.Contains(item) Then
                _contemNumeros = True
                Exit For
            End If
        Next

        If Not _contemNumeros Then

            _starIndex = 0
            _endIndex = (_arrLetrasMinusculas.Length - 1)
            _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
            _numeroStringSelecionado = _arrLetrasMinusculas(_posicaoSelecionada)

            _endIndex = (_senhaGerada.Length - 1)
            _posicaoJaSelecionada = True
            While _posicaoJaSelecionada
                _posicaoSelecionada = _random.Next(_starIndex, _endIndex)
                Dim _result = (From a As Integer In _posicoesSelecionadas Where a = _posicaoSelecionada Select a)
                If _result Is Nothing OrElse _result.Count() = 0 Then
                    _posicaoJaSelecionada = False
                End If
            End While
            _senhaGerada = _senhaGerada.Insert(_posicaoSelecionada, _numeroStringSelecionado)
            If _posicaoSelecionada = 0 Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada + 1, 1)
            ElseIf _posicaoSelecionada = _endIndex Then
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 2, 1)
            Else
                _senhaGerada = _senhaGerada.Remove(_posicaoSelecionada - 1, 1)
            End If

        End If

    End Sub

    Protected Sub AdicionaSimboloNaListaLista()
        Dim _listaChar() As Char

        _listaChar = Me.CaracteresEspeciais.ToCharArray()

        For Each item As Char In _listaChar
            Me.ArrayCaracteresSenha.Add(item.ToString())
        Next

    End Sub

    Protected Sub AdicionarNumeroNaLista()
        Dim _listaChar() As Char

        _listaChar = Me.Numeros.ToCharArray()

        For Each item As Char In _listaChar
            Me.ArrayCaracteresSenha.Add(item.ToString())
        Next
    End Sub

    Protected Sub AdicionarLetrasMinusculasNaLista()

        Dim _listaChar() As Char

        _listaChar = Me.LetrasMinusculas.ToCharArray()

        For Each item As Char In _listaChar
            Me.ArrayCaracteresSenha.Add(item.ToString())
        Next

    End Sub

    Protected Sub AdicionarLetrasMaiusculasNaLista()
        Dim _listaChar() As Char

        _listaChar = Me.LetrasMaiusculas.ToCharArray()

        For Each item As Char In _listaChar
            Me.ArrayCaracteresSenha.Add(item.ToString())
        Next

    End Sub

    Protected Function SenhaJaFoiGeradaNaSessao(ByVal _senhaGerada As String) As Boolean
        If Me.SenhasGeradas IsNot Nothing Then
            Dim _result = (From a As String In Me.SenhasGeradas Where String.Equals(a, _senhaGerada) Select a).FirstOrDefault
            If _result IsNot Nothing Then
                Return False
            Else
                Return True
            End If
        Else
            Return True
        End If
    End Function

#End Region

End Class